// Server Interface. Server can be TCP or UDP.
#if defined __linux__ || defined __CYGWIN__
#include <netdb.h>			// gethostbyname (), bind(), listen(), connect(), accept(), send(), receive()
#include <arpa/inet.h>		// inet_ntoa(), bind(), listen(), connect(), accept(), send(), receive()
#include <unistd.h>			// close()
#define close close
#else
#include <WinSock2.h>
#include <Windows.h>
#include <process.h>
#define close closesocket
#define socklen_t int
#endif

#define MAXBUFFERSIZE	512
#define TCPSOCKET		0
#define UDPSOCKET		1
#define DEFAULTSERVERPORT		6000
#define HEADERSIZE 6
#define NUMBEROFRESOURCES 2

class Server;
struct ClientNode;
struct DataForClientListeningThread;
struct DataForClientListeningThread
{
	Server* server_ptr_clients;
	Server* server_ptr_resource;
};
struct ClientNode
{
	int client_ID; // 0 to onward
	struct sockaddr_in client_address;	// Client's Address structure.
	int client_socket_FD;
	
	// Server's Buffer.
	char buffer[MAXBUFFERSIZE];
	int  num_of_bytes_received;
	int  num_of_bytes_sent;

	HANDLE client_thread_ID;
//	DataForClientThread* data_for_client_thread; //(may use this pointer)
	Server* server_ptr_clients;
	Server* server_ptr_resource;

	ClientNode* next_client_ptr;
	ClientNode* previous_client_ptr;
};

class Server
{
private:
	
	ClientNode* head_client_ptr;
	ClientNode* tail_client_ptr;

	int Type;		// TCP or UDP.
	// Addresses.
	struct sockaddr_in server_address;	// Server's Address structure.
	struct sockaddr_in their_address;	// Default address to sendto() and recvfrom() UDP packets.
	
	// File Descriptors.
	int server_socket_FD;

	// Miscellaneous Variables.
	int server_port;
	int error_check;

public:
	int AddNewClient(Server*);
	int AddNewResource();
	//int DeleteCurrentClient();

	Server(int = TCPSOCKET, int = DEFAULTSERVERPORT);
	// Socket function wrappers.
	int CreateSocket(int = TCPSOCKET);			// 0 = TCP, 1 = UDP; default is to create TCP socket.
	int SetSocketOptions();					// Set socket options to reuse address.
	int InitialiseAddress(int = DEFAULTSERVERPORT);	// Default Server port is 5000.
	int Bind();								// Bind Server socket with address.
	int Listen();								// Listen for incoming connections; for TCP Server.
	int Accept(ClientNode*);								// Accept incoming connections.

	// TCP send() and recv()
	int Send (void*, int, ClientNode*);
	int Receive(ClientNode*);
	int Receive(void*, int, ClientNode*);

	int CloseServerSocket();
	int CloseClientSocket(ClientNode*);

	// Additional functions.
	int GetType() { return Type; }
	int GetPort() { return server_port; }
	int GetErrorCheck() { return error_check; }

	int DisplayServerInfo();
	int DisplayClientInfo(ClientNode*);

	char* GetBuffer(ClientNode*);
	int GetNumOfBytesSent(ClientNode*);
	int GetNumOfBytesReceived(ClientNode*);

	friend void ThreadFunctionForClients(void*);
	friend void ThreadFunctionForResources(void*);
	friend void ThreadFunctionForClientListening(void*);
	friend void ThreadFunctionForResourceListening(void*);
	friend void ThreadFunctionForDistribution(void*);

};

